

import ij.IJ;
import ij.ImagePlus;
import ij.gui.NewImage;
import ij.plugin.filter.PlugInFilter;
import ij.process.Blitter;
import ij.process.ImageProcessor;

import pluginUtils.Complexe; 

import java.util.Random; 

/**
 * 
 */

/**
 * @author Francesco
 *
 */
public class DrostecopyFlickr_ implements PlugInFilter {
	private int imgCols; 
	private int imgRows;
	
	private double r1=0.2;
	private double r2=0.8; 
	
	private Random gen=new Random();
	
	/* (non-Javadoc)
	 * @see ij.plugin.filter.PlugInFilter#run(ij.process.ImageProcessor)
	 */
	public void run(ImageProcessor ip) {
		 //get width, height and the region of interest
			int w = ip.getWidth();     
			int h = ip.getHeight();  
			this.imgCols=w;
			this.imgRows=h;
			
			    
		

			// create a new image with the same size
			ImagePlus inverted = NewImage.createRGBImage ("New image", w, h, 1, NewImage.FILL_BLACK);
			ImageProcessor inv_ip = inverted.getProcessor();
			inv_ip.copyBits(ip,0,0,Blitter.COPY);

			int[] basepixels = (int[]) inv_ip.getPixels();
			int[] pixels=new int[this.imgCols*this.imgRows];
			
			
			double alpha=Math.atan(Math.log(r2/r1)/(2*Math.PI));
			Complexe ialpha=Complexe.createComplexeFromRI(Math.cos(alpha),Math.sin(alpha)); 
			Complexe beta=Complexe.mulbyDouble(ialpha, Math.cos(alpha));
			Complexe invBeta=Complexe.inverse(beta); 
			Complexe coef=Complexe.power(Complexe.createComplexeFromRI(r1/r2,0),beta);  
			Complexe invcoef=Complexe.power(Complexe.createComplexeFromRI(r2/r1,0),beta);  
			
			Complexe E=Complexe.createComplexeFromRI(Math.E,0); 
			double ratio;
			int maxIter=5; 
			int newX,newY; 
			    for(int xrow=0;xrow<imgRows;xrow++){
			    	for(int ycol=0;ycol<imgCols;ycol++){
			    		//System.out.println("boucle"); 
				    	// transform in [-log(r1/r2),log(r1/r2)]x[-pi,pi]
				    	double x0=-Math.log(r2/r1)+(xrow+0.0)/imgRows*2*Math.log(r2/r1); 
				    	double y0=(ycol+0.0)/imgCols*2*Math.PI-Math.PI;
				    
				    	Complexe z=Complexe.createComplexeFromRI(x0,y0);
				    	
				    
				    	
				    	z=Complexe.mulbyDouble(z,1/r1); 
				    	z=Complexe.log(z);
				    	z=Complexe.mul(z,invBeta);
				    	z=Complexe.power(E,z);
				    	z=Complexe.mulbyDouble(z, r1); 
				    	
				    	double coordx=(z.getReal()+1)*imgRows/2; 
				    	double coordy=(z.getIm()+1)*imgCols/2;
				    	double r=Math.sqrt(z.squareNorm()); 
				    	if(r<r1) ratio=r2/r1; else ratio=r1/r2; 
				    	int iter=0; 
				    	while(((r<r1)||(r>r2))&&(iter++<maxIter)){
				    		z=Complexe.mulbyDouble(z, ratio); 
				    		coordx=(z.getReal()+1)*imgRows/2; 
					    	coordy=(z.getIm()+1)*imgCols/2;
					    	//r=z.norm(); 
				    	}
				    	
			    		newX=(int)coordx; 
			    		newY=(int)coordy; 
			    		
			    		if(gen.nextDouble()<0.001)System.out.println("--->"+coordx+" "+coordy); 
				    
				    	try{
				    		if((newX<imgRows)&&(newY<imgCols)&&(newX>=0)&&(newY>=0))
				    			if(pixels[(int)(newX*imgCols+newY)]==0)
				    		pixels[(int)(newX*imgCols+newY)]=basepixels[xrow*imgCols+ycol];
				    	}
				    	catch(Exception e){System.err.println("Index out of bounds");}
				  
			    	}// for ycol
			    	System.out.println("Row : "+xrow);
			   
			    }
			 inv_ip.setPixels(pixels); 
			 inverted.show();
			 inverted.updateAndDraw();
	
			    	
}
	
	
			
	

	/* (non-Javadoc)
	 * @see ij.plugin.filter.PlugInFilter#setup(java.lang.String, ij.ImagePlus)
	 */
	
	public int setup(String arg, ImagePlus imp) {
		if (arg.equals("about"))
			{showAbout(); return DONE;}
	            return DOES_RGB+NO_CHANGES;

	}
	
	void showAbout() {
		IJ.showMessage("Droste effect",
			"Escher-like droste effect"
		); 

	}
}